#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<dirent.h>
#include<sys/stat.h>
#include<unistd.h>
#include<sys/stat.h>

void dump_mode(struct stat *attr)
{
    int mode=attr->st_mode & 0x1ff;
    int u=(mode >> 6) & 7;
    int g=(mode >>3) & 7;
    int o=mode & 7;
    switch(u)
    {
        case 7:
            printf("rwx");
            break;
        case 6:
            printf("rw-");
            break;
        case 5:
            printf("r-x");
            break;
        case 4:
            printf("r--");
            break;
        case 3:
            printf("-wx");
            break;
        case 2:
            printf("-w-");
            break;
        case 1:
            printf("--x");
            break;
        case 0:
            printf("---");
            break;
    }
    switch(g)
    {
        case 7:
            printf("rwx");
            break;
        case 6:
            printf("rw-");
            break;
        case 5:
            printf("r-x");
            break;
        case 4:
            printf("r--");
            break;
        case 3:
            printf("-wx");
            break;
        case 2:
            printf("-w-");
            break;
        case 1:
            printf("--x");
            break;
        case 0:
            printf("---");
            break;
    }
    switch(o)
    {
        case 7:
            printf("rwx");
            break;
        case 6:
            printf("rw-");
            break;
        case 5:
            printf("r-x");
            break;
        case 4:
            printf("r--");
            break;
        case 3:
            printf("-wx");
            break;
        case 2:
            printf("-w-");
            break;
        case 1:
            printf("--x");
            break;
        case 0:
            printf("---");
            break;
    }
}

void list_dir(char *path)
{
    DIR *dir=opendir(path);
    struct dirent *entry;
    if(dir==NULL)
    {
        printf("File path error!\n");
        return;
    }
    while(entry=readdir(dir))
    {
        if(strcmp(entry->d_name,".")==0)
            continue;
        else if(strcmp(entry->d_name,"..")==0)
            continue;
        else if(entry->d_type==DT_DIR)
            printf("dir %s\n",entry->d_name);
        else if(entry->d_type==DT_REG)
            printf("file %s\n",entry->d_name);
    }
    closedir(dir);
}

void list_dir2(char *path)
{
    DIR *dir=opendir(path);
    struct dirent *entry;
    if(dir==NULL)
    {
        printf("File path error!\n");
        return;
    }
    int filetype;
    char filename[256];
    while(entry=readdir(dir))
    {
        if(strcmp(entry->d_name,".")==0)
            continue;
        else if(strcmp(entry->d_name,"..")==0)
            continue;
        else if(entry->d_type==DT_DIR)
        {
            strcpy(filename,entry->d_name);
            filetype=1;
        }
        else if(entry->d_type==DT_REG)
        {
            strcpy(filename,entry->d_name);
            filetype=0;
        }
        struct stat attr;
        stat(filename,&attr);
        dump_mode(&attr);
        printf(" ");
        if(filetype)
            printf("dir %s\n",filename);
        else
            printf("file %s\n",filename);
    }
    closedir(dir);
}

int main(int argc,char *argv[])
{
    if(argc==1)
    {
        list_dir("./");
    }
    else if(argc==2&&strcmp(argv[1],"-l")==0)
    {
        list_dir2("./");
    }
    else if(argc==2&&strcmp(argv[1],"-l")!=0)
    {
        list_dir(argv[1]);
    }
    else if(argc==3&&strcmp(argv[1],"-l")==0)
    {
        list_dir2(argv[2]);
    }
    else
    {
        printf("Instruction format error!\n");
        return 0;
    }
    return 0;
}
